package com.echo.register.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.echo.register.common.exception.RegisterException;
import com.echo.register.common.result.ResultCodeEnum;
import com.echo.register.enums.PaymentTypeEnum;
import com.echo.register.enums.RefundStatusEnum;
import com.echo.register.model.order.OrderInfo;
import com.echo.register.model.order.PaymentInfo;
import com.echo.register.model.order.RefundInfo;
import com.echo.register.order.service.OrderService;
import com.echo.register.order.service.PaymentService;
import com.echo.register.order.service.RefundInfoService;
import com.echo.register.order.service.WeixinService;
import com.echo.register.order.utils.ConstantPropertiesUtils;
import com.echo.register.order.utils.HttpClient;
import com.github.wxpay.sdk.WXPayUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName: WeixinServiceImpl
 * @Package: com.echo.register.order.service.impl
 * @Description:
 * @Author 谢同学
 * @Create 2024/1/8 17:03
 * @Version 1.0
 */
@Service
public class WeixinServiceImpl implements WeixinService {

    @Autowired
    private OrderService orderService;
    @Autowired
    private PaymentService paymentService;
    @Autowired
    private RefundInfoService refundInfoService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 根据订单号  生成支付链接
     *
     * @param orderId 订单号
     * @return 支付参数
     */
    @Override
    public Map<String, Object> createNative(Long orderId) {
        // 首先查询缓存中有没有支付连接
        String value = redisTemplate.opsForValue().get(String.valueOf(orderId));
        if (!StringUtils.isEmpty(value)) {
            return JSONObject.parseObject(value, Map.class);
        }
        //根据订单id查询订单信息
        OrderInfo orderInfo = orderService.getOrderInfo(orderId);
        if (orderInfo == null) {
            throw new RegisterException(ResultCodeEnum.PARAM_ERROR);
        }
        // 保存交易记录
        paymentService.savePsavePaymentInfo(orderInfo, PaymentTypeEnum.WEIXIN.getStatus());
        //调用微信统一下单接口

        // 1、设置参数
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("appid", ConstantPropertiesUtils.APPID); //公众号id
        paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER); // 商户号
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());// 随机字符串
        paramMap.put("out_trade_no", orderInfo.getOutTradeNo()); // 订单号
        paramMap.put("body", orderInfo.getReserveDate() + "就诊" + orderInfo.getDepname()); // 订单描述
        //paramMap.put("total_fee", orderInfo.getAmount().multiply(new BigDecimal("100")).longValue()+"");// 订单金额
        paramMap.put("total_fee", "1");// 订单金额 测试使用
        paramMap.put("spbill_create_ip", "127.0.0.1"); // 终端ip
        //paramMap.put("time_expire", new DateTime().plusMillis(3).toString("yyyyMMddHHmmss"));// 交易结束时间
        paramMap.put("notify_url", "https://2495161sb6.goho.co/api/order/weixinPay/weixinNotify"); //通知地址
        paramMap.put("trade_type", "NATIVE"); //交易类型

        Map<String, String> resultMap = new HashMap<>();
        //2、HTTPClient来根据URL访问第三方接口并且传递参数
        try {
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
            //client设置参数
            client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY));
            client.setHttps(true);
            // 发送请求
            client.post();
            //3、返回第三方的数据
            String xml = client.getContent();
            resultMap = WXPayUtil.xmlToMap(xml);
        } catch (Exception e) {
            throw new RegisterException("对接微信统一下单接口失败", ResultCodeEnum.FAIL.getCode());
        }
        //4、封装返回结果集
        if (resultMap.get("return_code").equals("SUCCESS") && resultMap.get("result_code").equals("SUCCESS")) {
            Map<String, Object> map = new HashMap<>();
            map.put("orderId", orderId);
            map.put("totalFee", orderInfo.getAmount());
            map.put("resultCode", resultMap.get("result_code"));
            map.put("codeUrl", resultMap.get("code_url"));
            // 将二维码放入redis中，设置有效时间
            if (resultMap.get("result_code") != null) {
                redisTemplate.opsForValue().set(String.valueOf(orderId), JSONObject.toJSONString(map), 1, TimeUnit.MINUTES);
            }
            return map;

        } else {
            throw new RegisterException(resultMap.get("return_msg") + " " + resultMap.get("err_code_des"), ResultCodeEnum.FAIL.getCode());
        }

    }

    /**
     * 对接微信查询接口，查询支付状态
     *
     * @param orderId     订单id
     * @param paymentType 支付类型
     * @return Map<String, String> 微信响应数据
     */
    @Override
    public Map<String, String> queryPayStatus(Long orderId, String paymentType) {
        //根据订单id查询订单信息
        OrderInfo orderInfo = orderService.getOrderInfo(orderId);
        if (orderInfo == null) {
            throw new RegisterException(ResultCodeEnum.PARAM_ERROR);
        }
        //1、封装参数
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("appid", ConstantPropertiesUtils.APPID); //公众号id
        paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER); // 商户号
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());// 随机字符串
        paramMap.put("out_trade_no", orderInfo.getOutTradeNo()); // 订单号
        try {
            //2、设置请求
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
            client.setHttps(true);
            client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY));
            client.post();
            // 3、返回第三方的数据，转成map
            String xml = client.getContent();
            // 4、返回
            return WXPayUtil.xmlToMap(xml);
        } catch (Exception e) {
            throw new RegisterException("查询结果失败", ResultCodeEnum.FAIL.getCode());
        }
    }

    /**
     * 对接微信退款接口
     *
     * @param orderId 订单id
     * @return 是否退款成功
     */
    @Override
    public Boolean refund(Long orderId) {
        // 保存退款记录

        // 获取订单信息
        PaymentInfo paymentInfo = paymentService.getPaymentInfo(orderId, PaymentTypeEnum.WEIXIN.getStatus());
        if (paymentInfo == null) {
            throw new RegisterException(ResultCodeEnum.DATA_ERROR);
        }
        // 保存退款记录
        RefundInfo refundInfo = refundInfoService.saveRefundInfo(paymentInfo);
        // 判断是否已经退款
        if (Objects.equals(refundInfo.getRefundStatus(), RefundStatusEnum.REFUND.getStatus())) {
            return true;
        }

        // 对接微信退款接口

        // 组装参数
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("appid", ConstantPropertiesUtils.APPID);       //公众账号ID
        paramMap.put("mch_id", ConstantPropertiesUtils.PARTNER);   //商户编号
        paramMap.put("nonce_str", WXPayUtil.generateNonceStr());  // 商户号
        paramMap.put("transaction_id", paymentInfo.getTradeNo()); //微信订单号
        paramMap.put("out_trade_no", paymentInfo.getOutTradeNo()); //商户订单编号
        paramMap.put("out_refund_no", "tk" + paymentInfo.getOutTradeNo()); //商户退款单号
        //paramMap.put("total_fee",paymentInfoQuery.getTotalAmount().multiply(new BigDecimal("100")).longValue()+""); // 订单金额
        //paramMap.put("refund_fee",paymentInfoQuery.getTotalAmount().multiply(new BigDecimal("100")).longValue()+""); // 退款金额
        paramMap.put("total_fee", "1");
        paramMap.put("refund_fee", "1");
        Map<String, String> resultMap = new HashMap<>();
        try {
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/secapi/pay/refund");
            client.setHttps(true);
            client.setCert(true); // 需要证书
            client.setCertPassword(ConstantPropertiesUtils.PARTNER); // 证书密码默认为商户号
            client.setXmlParam(WXPayUtil.generateSignedXml(paramMap, ConstantPropertiesUtils.PARTNERKEY));
            client.post();
            // 获取响应数据
            String content = client.getContent();
            resultMap = WXPayUtil.xmlToMap(content);

        } catch (Exception e) {
            throw new RegisterException("微信退款失败",ResultCodeEnum.FAIL.getCode());
        }
        if (resultMap.get("return_code").equals("SUCCESS") && resultMap.get("result_code").equals("SUCCESS")) {
            // 更新退款记录
            refundInfo.setTradeNo(resultMap.get("refund_id"));
            refundInfo.setRefundStatus(RefundStatusEnum.REFUND.getStatus());// 2 已退款
            refundInfo.setCallbackTime(new Date());
            refundInfo.setCallbackContent(JSONObject.toJSONString(resultMap));
            refundInfoService.updateById(refundInfo);
            return true;
        } else {
            throw new RegisterException(resultMap.get("return_msg") + " " + resultMap.get("err_code_des"), ResultCodeEnum.FAIL.getCode());
        }

    }
}
